package com.fulihui.information.biz.job;

import com.fulihui.information.biz.conv.ContentConv;
import com.fulihui.information.common.config.AppConst;
import com.fulihui.information.core.redis.RedisBasicCategoryContentSortDB;
import com.fulihui.information.core.redis.RedisContentListItemDB;
import com.fulihui.information.core.redis.RedisHotsContentReadTimesSortDB;
import com.fulihui.information.core.redis.RedisHotsContentSharedTimesSortDB;
import com.fulihui.information.dal.dataobj.InfoCategory;
import com.fulihui.information.dal.dataobj.InfoCategoryExample;
import com.fulihui.information.dal.dataobj.InfoContent;
import com.fulihui.information.dal.dataobj.InfoContentExample;
import com.fulihui.information.dal.mapper.ExtInfoContentListItemMapper;
import com.fulihui.information.dal.mapper.InfoCategoryMapper;
import com.fulihui.information.dto.ContentListItemDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.fulihui.information.util.ContentScoreUtil.*;
import static java.util.Collections.emptyList;
import static org.near.toolkit.common.StringUtil.EMPTY_STRING;
import static org.springframework.util.CollectionUtils.isEmpty;

/**
 * 初始化内容到Redis，每天凌晨执行一次，往Redis中输入最新的10000条数据
 *
 * @author Willard.Hu on 2017/1/12 0012.
 */
public class InitRedisContentJob     {
    private final transient Logger log = LoggerFactory.getLogger(getClass());

    private final static int LIMIT_COUNT = 10000;

    @Autowired
    private RedisBasicCategoryContentSortDB   redisBasicCategoryContentSortDB;
    @Autowired
    private RedisHotsContentReadTimesSortDB   redisHotsContentReadTimesSortDB;
    @Autowired
    private RedisHotsContentSharedTimesSortDB redisHotsContentSharedTimesSortDB;
    @Autowired
    private RedisContentListItemDB            redisContentListItemDB;
    @Autowired
    private ExtInfoContentListItemMapper      extInfoContentListItemMapper;
    @Autowired
    private InfoCategoryMapper                infoCategoryMapper;


    public void execute(   ) {
        List<String> categoryCodes = categoryCodes();
        if (isEmpty(categoryCodes)) {
            log.warn("没有有效的类目，无法同步到Redis中");
            return;
        }
        categoryCodes.forEach(it -> {
            try {
                doInitCategory(it);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        });
    }

    private void doInitCategory(String categoryCode) {
        InfoContentExample example = new InfoContentExample();
        example.createCriteria().andCategoryCodeEqualTo(categoryCode)
                .andTopStatusEqualTo("0")
                .andStatusEqualTo("CHECK");
        for (int start = 0, rows = 500; start < LIMIT_COUNT; start += rows + 1) {
            List<InfoContent> list = extInfoContentListItemMapper.selectListItemPage(example, start, rows);
            if (isEmpty(list)) {
                break;
            }
            List<ContentListItemDTO> items = ContentConv.toList(list, ContentListItemDTO.class);
            redisContentListItemDB.batchSave(items);
            Map<String, Double> params = new HashMap<>();
            items.forEach(item -> params.put(item.getId(), categoryScore(item)));
            redisBasicCategoryContentSortDB.bathSave(params, categoryCode);
            // 段子不加入到热门中
            if (!"YOUKANTOU_ESSAY_JOKE".equals(categoryCode)) {
                Map<String, Double> hotsParams = new HashMap<>();
                items.forEach(item -> hotsParams.put(item.getId(), hotsReadTimesScore(item)));
                redisHotsContentReadTimesSortDB.bathSave(hotsParams, EMPTY_STRING);

                Map<String, Double> hotsParams2 = new HashMap<>();
                items.forEach(item -> hotsParams2.put(item.getId(), hotsSharedTimesScore(item)));
                redisHotsContentSharedTimesSortDB.bathSave(hotsParams2, EMPTY_STRING);
            }
        }
    }

    private List<String> categoryCodes() {
        InfoCategoryExample example = new InfoCategoryExample();
        example.createCriteria().andProductCodeEqualTo("YOUKANTOU")
                .andParentCodeIsNull()
                .andProductCodeNotEqualTo(AppConst.CONTENT_HOTS_CATEGORY_CODE);
        List<InfoCategory> list = infoCategoryMapper.selectByExample(example);
        if (isEmpty(list)) {
            return emptyList();
        }
        return list.stream().map(InfoCategory::getCode).collect(Collectors.toList());
    }
}
